package com.wrx.club_management_backend.controller;

import cn.hutool.core.util.RandomUtil;
import com.wrx.club_management_backend.common.AjaxResult;
import com.wrx.club_management_backend.mapper.UserMapper;
import com.wrx.club_management_backend.service.MsgService;
import com.wrx.club_management_backend.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.security.MessageDigest;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.wrx.club_management_backend.utils.RedisConstant.*;

@RestController
@RequestMapping("/sys")
public class SysController {

    public static String UPLOAD_PATH = "file:C:\\Users\\23296\\Desktop\\club-system-front-end\\club_management_backend\\club_management_backend\\upload\\";

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    UserMapper userMapper;

    @Autowired
    UserService userService;

    private static final Pattern SNO_PATTERN = Pattern.compile("/^20\\d{2}1204140\\d{3}$/");

    @Autowired
    MsgService msgService;

    @GetMapping("/dep")
    public AjaxResult dep(){
        // 查询数据库

        Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(SYS_DEP);
        stringRedisTemplate.expire(SYS_DEP, CACHE_TTL, TimeUnit.MINUTES);
        return AjaxResult.success(map);
    }

    @GetMapping("/msg/{id}")
    public AjaxResult msg(@PathVariable("id") Long id){
        return msgService.sysmsg(id);
    }

    /**
     * 计算文件的MD5值
     */
    private String calculateMD5(MultipartFile file) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(file.getBytes());
            byte[] digest = md.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 处理图片上传，按照年/月/日目录存储，同一天相同文件不重复上传
     */
    @PostMapping("/upload")
    public AjaxResult uploadImage(@RequestParam("file") MultipartFile file) {
        try {
            if (file.isEmpty()) {
                return AjaxResult.error("上传的文件不能为空");
            }

            String contentType = file.getContentType();
            if (contentType == null || !contentType.startsWith("image/")) {
                return AjaxResult.error("只能上传图片文件");
            }

            // 生成日期目录
            LocalDate now = LocalDate.now();
            String datePath = String.format("%d/%02d/%02d",
                    now.getYear(),
                    now.getMonthValue(),
                    now.getDayOfMonth());

            // 计算文件MD5
            String fileMD5 = calculateMD5(file);
            if (fileMD5 == null) {
                return AjaxResult.error("文件处理失败");
            }

            // 检查Redis中是否存在该文件的记录（使用日期+MD5作为key）
            String redisKey = "upload:" + datePath + ":" + fileMD5;
            String existingPath = stringRedisTemplate.opsForValue().get(redisKey);

            if (existingPath != null) {
                // 文件今天已经上传过，直接返回已存在的URL
                return AjaxResult.success("文件已存在", existingPath);
            }

            // 文件没有上传过，进行新的上传
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String newFilename = UUID.randomUUID().toString() + extension;

            String baseDir = UPLOAD_PATH.substring(5); // 移除 "file:" 前缀
            String fullPath = baseDir + datePath;
            File uploadDir = new File(fullPath);

            if (!uploadDir.exists()) {
                boolean created = uploadDir.mkdirs();
                if (!created) {
                    return AjaxResult.error("创建目录失败");
                }
            }

            File destFile = new File(uploadDir.getAbsolutePath() + File.separator + newFilename);
            file.transferTo(destFile);

            // 生成访问URL
            String accessUrl = "http://localhost:8080/uploads/" + datePath.replace('\\', '/') + "/" + newFilename;

            // 将文件信息存入Redis，设置24小时过期
            stringRedisTemplate.opsForValue().set(redisKey, accessUrl, 24, TimeUnit.HOURS);

            return AjaxResult.success("图片上传成功", accessUrl);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error("图片上传失败：" + e.getMessage());
        }
    }

    @PostMapping("/getCode")
    public AjaxResult getCode(){
        Set<String> members = stringRedisTemplate.opsForSet().members(SYS_CODE);
        assert members != null;
        List<String> codes = new ArrayList<>(members);
        return AjaxResult.success(codes);
    }

    @PostMapping("/delCode/{code}")
    public AjaxResult delCode(@PathVariable("code") String code){
        stringRedisTemplate.opsForSet().remove(SYS_CODE, code);
        return AjaxResult.success("删除成功");
    }

    @PostMapping("/genCode/{count}")
    public AjaxResult genCode(@PathVariable("count") int count){
        List<String> codes = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            String code = RandomUtil.randomString(8).toUpperCase();
            codes.add(code);
        }
        for(int i = 0;  i< count; i ++) stringRedisTemplate.opsForSet().add(SYS_CODE, codes.get(i));
        return AjaxResult.success(codes);
    }

    @PostMapping("/getSno")
    public AjaxResult getSno(){
        Set<String> members = stringRedisTemplate.opsForSet().members(SYS_SNO);
        List<String> list = new ArrayList<>(members);
        List<Map<String, Object>> maps = userMapper.checkSnosRegistrationStatus(list);
        assert msgService != null;
        return AjaxResult.success(maps);
    }

    @PostMapping("/delSno/{phone}")
    public AjaxResult delSno(@PathVariable("phone") String sno){
        stringRedisTemplate.opsForSet().remove(SYS_SNO, sno);
        // 删除用户
        userService.delUser(sno);
        return AjaxResult.success("删除成功");
    }

    /**
     * 批量添加手机号
     * @param snos 手机号列表
     * @return 添加结果
     */
    @PostMapping("/addSno")
    public AjaxResult addSnos(@RequestBody List<String> snos) {
        if (snos == null || snos.isEmpty()) {
            return AjaxResult.error("学号列表不能为空");
        }

        try {
            // 过滤出有效的手机号
            List<String> validSnos = snos.stream()
                    .filter(sno -> SNO_PATTERN.matcher(sno).matches())
                    .collect(Collectors.toList());

            if (validSnos.isEmpty()) {
                return AjaxResult.error("没有有效学号");
            }

            // 批量添加到Redis Set中
            Long addedCount = stringRedisTemplate.opsForSet().add(SYS_SNO,
                    validSnos.toArray(new String[0]));

            // 构建返回结果
            Map<String, Object> data = new HashMap<>();
            data.put("successCount", addedCount);
            data.put("invalidCount", snos.size() - validSnos.size());
            data.put("totalCount", snos.size());

            return AjaxResult.success(data);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("添加失败：" + e.getMessage());
        }
    }

    @PostMapping("/fundTypes")
    public AjaxResult getFundTypes(){
        Map<Object, Object> map = stringRedisTemplate.opsForHash().entries("sys:fundType");
        List<Map<Object, Object>> list = new ArrayList<>();
        Set<Object> objects = map.keySet();
        for (Object object : objects) {
            Map<Object, Object> temp = new HashMap<>();
            temp.put("value", object);
            temp.put("name", map.get(object));
            list.add(temp);
        }
        return AjaxResult.success(list);
    }


}
